﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization.Json;
using System.ServiceModel;
using System.Web.Script.Serialization;
using Application.Core.EntityService;
using Application.Core.ErrorHandlers;
using Domain.MainModule.Entities;
using Domain.MainModule.Repositories;
using Infrastructure.CrossCutting.Caching;
using System.ServiceModel.Activation;
using Presentation.Web.Core.Pagination;

namespace Application.MainModule.DinnerManagement
{
    [ApplicationErrorHandler()] 
    [AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
    [ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall)]
    public class DinnerManagementService : BaseService<Dinners,int>,IDinnerManagementService
    {
        #region Members
        private readonly IDinnerRepository _dinnerRepository;
        private readonly IRSVPRepository _rsvpRepository;
        private readonly ICache _cache;
        #endregion
        private IEnumerable<Dinners> All
        {
            get
            {
                return GetAll("AllDinner");
            }
        }
        private IEnumerable<Dinners> AllIncludRSVP
        {
            get
            {
                return GetAll("AllDinnerIncludRSVPs", p => p.RSVPs);
            }
        }
        #region Constructor

        /// <summary>
        /// Create new instance 
        /// </summary>
        ///<param name="dinnerRepository"> </param>
        ///<param name="cache"> </param>
        ///<param name="rsvpRepository"> </param>
        ///this is give the wcf
        public DinnerManagementService(IDinnerRepository dinnerRepository, ICache cache, IRSVPRepository rsvpRepository) :base(dinnerRepository,cache)
        {
            if (dinnerRepository == (IDinnerRepository)null)
                throw new ArgumentNullException("dinnerRepository");

            if (cache == (ICache)null)
                throw new ArgumentNullException("cache");

            _dinnerRepository = dinnerRepository;
            _rsvpRepository = rsvpRepository;
            _cache = cache;

        }

      
        #endregion

        public IEnumerable<Dinners> GetMostPopularDinners(int limit)
        {
            var mostPopularDinner = from dinner in AllIncludRSVP
                                    orderby dinner.RSVPs.Count descending
                                    select dinner;
            return mostPopularDinner.Take(limit);
           
        }

        public GaryDTO GetDinners(int limit)
        {
            var jsonserializer = new JavaScriptSerializer();
            var result = jsonserializer.Deserialize<GaryDTO>("{\"StudentName\":\"Shen Xiu\",\"StudentId\":1001,\"Date\":\"2012-7-20,Fri\",\"AvailableCredits\":23,\"Notifications\":[{\"Type\":1,\"Date\":\"2012-7-20\",\"Title\":\"EF Earth Hour\"},{\"Type\":1,\"Date\":\"2012-7-10\",\"Title\":\"EF Earth Hour\"}],\"LifeClubEvents\":[{\"Date\":\"2012-7-23\", \"Events\":[{\"Title\":\"The little green explorer\",\"Content\":\"About the environment, natural resources and the world. Proin lectus augue, iaculis a posuere.\",\"Time\":\"8:30 pm\",\"Cost\":4,\"Status\":1},{\"Title\":\"The little green explorer\",\"Content\":\"About the environment, natural resources and the world. Proin lectus augue, iaculis a posuere.\",\"Time\":\"8:30 pm\",\"Cost\":4,\"Status\":2}]},{\"Date\":\"2012-7-25\",\"Events\":[{\"Title\":\"The little green explorer\",\"Content\":\"About the environment, natural resources and the world. Proin lectus augue, iaculis a posuere.\",\"Time\":\"8:10 pm\",\"Cost\":4,\"Status\":3},{\"Title\":\"The little green explorer\",\"Content\":\"About the environment, natural resources and the world. Proin lectus augue, iaculis a posuere.\",\"Time\":\"8:30 pm\",\"Cost\":4,\"Status\":4},{\"Title\":\"The little green explorer\",\"Content\":\"About the environment, natural resources and the world. Proin lectus augue, iaculis a posuere.\",\"Time\":\"8:30 pm\",\"Cost\":4,\"Status\":1}]}],Medias:[{\"big\":\"url1\",\"small\":\"url2\"},{\"big\":\"url1\",\"small\":\"url2\"}]}");
            return result;
            //var mostPopularDinner = from dinner in AllIncludRSVP
            //                        select dinner.ToDinnerDTO();
            //return mostPopularDinner.Take(limit).ToList();
        }

        public IPagination<Dinners> FindPagedDinners(int pageNumner, int pageSize)
        {
            return All.AsPagination(pageNumner, pageSize);
        }
        public IEnumerable<Dinners> FindUpcomingDinners()
        {
            return from dinner in All
                   where dinner.EventDate <= DateTime.Now
                   orderby dinner.EventDate
                   select dinner;

        }
        
        public IEnumerable<Dinners> FindDinnersByText(string q)
        {
            return All.Where(d => d.Title.Contains(q)
                            || d.Description.Contains(q)
                            || d.HostedBy.Contains(q));
        }

        public IEnumerable<Dinners> FindByLocation(float latitude, float longitude)
        {
            return All;
        }

        public IEnumerable<Dinners> FindMyDinners(string userName)
        {
            return from dinner in AllIncludRSVP
                   where
                     (
                         String.Equals((dinner.HostedById ?? dinner.HostedBy), userName) ||
                         dinner.RSVPs.Any(r => r.AttendeeNameId == userName || (r.AttendeeNameId == null && r.AttendeeName == userName))
                     )
                   orderby dinner.EventDate
                   select dinner;
        }

        public Dinners FindDinner(int id)
        {
            return AllIncludRSVP.SingleOrDefault(p => p.DinnerID == id);
        }

        public void InsertOrUpdateDinner(Dinners dinner)
        {
            if (dinner.DinnerID == default(int))
            {
                _dinnerRepository.Add(dinner);
            }
            else
            {
                _dinnerRepository.Modify(dinner);
            }
        }

        public void DeleteDinner(int id)
        {
            var dinner = FindDinner(id);
            foreach (RSVPs rsvp in dinner.RSVPs.ToList())
            {
                dinner.RSVPs.Remove(rsvp);
            }
            _dinnerRepository.Remove(dinner);
        }
        public void DeleteRSVP(RSVPs rsvp)
        {
            _rsvpRepository.Remove(rsvp);
        }
        public void Save()
        {
            _dinnerRepository.UnitOfWork.CommitAndRefreshChanges();
            _cache.Remove(new CacheKey("AllDinner"));
            _cache.Remove(new CacheKey("AllDinnerIncludRSVPs"));

        }
    }
}
